package main

import (
	"gorm.io/gorm"
)

// User 用户表 一个用户用有多篇文章
type User struct {
	ID       uint
	Name     string `gorm:"type:varchar(20)"`
	Articles []Articles
}

// Articles 一篇文章属于一个用户
type Articles struct {
	ID     uint
	Title  string `gorm:"type:varchar(30)"`
	UserID uint   //表名+ID就是 外键名称
	User   User
}

/*
重写外键关联 UID
User 用户表 一个用户用有多篇文章

		type User struct {
			ID       uint
			Name     string `gorm:"type:varchar(20)"`
			Articles []Articles `gorm:"foreignKey:UID"`
		}
	 Articles 一篇文章属于一个用户
		type Articles struct {
			ID     uint
			Title  string `gorm:"type:varchar(30)"`
			UID uint
			User  User `gorm:"foreignKey:UID"` //重写外键关联  将之前的外键UserID 修改为UID 则需要重写外键关联
		}
*/
/*
	重写外键引用 references
// User 用户表 一个用户用有多篇文章
type User struct {
	ID       uint
	Name     string `gorm:"type:varchar(20)"`
	Articles []Articles `gorm:"foreignKey:UserName;references:Name"`
}

// Articles 一篇文章属于一个用户
type Articles struct {
	ID     uint
	Title  string `gorm:"type:varchar(30)"`
	UserName string
	User   User `gorm:"references:Name"`
}
*/
func main() {
	//DB.AutoMigrate(&User{}, &Articles{})
	DB = DB.Session(&gorm.Session{
		Logger: mysqlLogger,
	})
	/*
		1.1 创建用户 带上文章
		DB.Create(&User{
			Name: "test",
			Articles: []Articles{
				{
					Title: "python",
				},
				{
					Title: "golang",
				},
			},
		})
		1.2 创建文章 关联已有用户
		DB.Create(&Articles{
			Title:  "学习python",
			UserID: 1,
		})
		1.3创建文章 并创建用户
		DB.Create(&Articles{
			Title: "学习golang",
			User: User{
				Name: "张三",
			},
		})
		1.4 创建文章,带上用户的对象
		var user User
		DB.Take(&user, 2)
		DB.Create(&Articles{
			Title: "张三写的golang",
			User:  user,
		})
		2.1 外键添加 给已有用户绑定文章
		var user User
		DB.Take(&user, 1) //等价于 SELECT * FROM `users` WHERE `users`.`id` = 1 LIMIT 1
		var article Articles
		DB.Take(&article, 6)                                     //等价于 SELECT * FROM `articles` WHERE `articles`.`id` = 6 LIMIT 1
		DB.Model(&user).Association("Articles").Append(&article) //等价于给前两步中查出来的用户绑定查出来的文章 即INSERT INTO `articles` (`title`,`user_id`,`id`) VALUES ('test写的python',1,6) ON DUPLICATE KEY UPDATE `user_id`=VALUES(`user_id`)
		//2.2 外键添加 给已有文章绑定用户
		var user User
		DB.Take(&user, 1) //等价于 SELECT * FROM `users` WHERE `users`.`id` = 1 LIMIT 1
		var article Articles
		DB.Take(&article, 6)                                 //等价于 SELECT * FROM `articles` WHERE `articles`.`id` = 6 LIMIT 1
		DB.Model(&article).Association("User").Append(&user) //INSERT INTO `users` (`name`,`id`) VALUES ('test',1) ON DUPLICATE KEY UPDATE `id`=`id`
	*/
	/*
		//  1.1 这样只能查出来第一条文章，并不能查出来这个文章对应的用户信息
		// 即 SELECT * FROM `articles` LIMIT 1 --> {1 python 1 {0  []}}
		var article Articles
		//DB.Take(&article)
		// 为了在查找文章时 也查找出来这个文章对应的用户信息 则应该使用以下查找方式 预加载Preload 此处这个User就是Articles这个结构体中定义的字段
		DB.Preload("User").Take(&article) // SELECT * FROM `users` WHERE `users`.`id` = 1 ; SELECT * FROM `articles` LIMIT 1 --> {1 python 1 {1 test []}}
		fmt.Println(article)
		//1.2 嵌套预加载
		var user User
		DB.Preload("Articles.User").Take(&user) //查找用户对象有哪些文章,并打印出文章对应的用户信息
		fmt.Println(user)
		//1.3 带条件的预加载
		var user User
		DB.Preload("Articles", "id >?", 2).Take(&user) //查找用户对象的文章id大于2的文章
		fmt.Println(user)
	*/
	/*
	//删除
	// 1.1 级联删除  删除用户时 与用户关联的文章也被删除
	var user User
	DB.Take(&user, 1)
	DB.Select("Articles").Delete(&user)
	// 1.2 清除外键关系 删除用户,将与该用户关联的文章外键设置为null
	var user User
	DB.Preload("Articles").Take(&user, 2)
	DB.Model(&user).Association("Articles").Delete(&user.Articles) //清除外键关系
	DB.Delete(&user) //删除用户
	 */
}
